/**
 * Name: main.c
 * Author: zuoyanyouwu
 * simulate system's kye or mouse 
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/input.h>
#include <fcntl.h>
#include <sys/time.h>
#include <unistd.h>

#include "debug.h"
#include "unp.h"
#include "daemon.h" 

#define SERVER_PORT 2015

static void read_code(int sockfd, int fd_kb);
static void send_code(int fd, int type, int value, int code);
static void simulate_key(int fd, int *kval, int n);

int main(int argc, char *argv[]) {

    int fd_kb, sock_fd, conn_fd;
	
	pid_t pid;
	socklen_t clilen;
	struct sockaddr_in servaddr, cliaddr;

	init_daemon(argv[0], LOG_KERN);

	fd_kb = open ("/dev/input/event4", O_RDWR);
    if (fd_kb < 0) {
    	printf("open error\n");
    	return 0;
    }

	if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		perror("socket");
		return -1;
	}

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(SERVER_PORT);
	servaddr.sin_addr.s_addr = INADDR_ANY;
	if (bind(sock_fd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr))== -1) {
		perror("socket bind");
		return -1;
	}
	DEBUG();
	if (listen(sock_fd, 1024) == -1) {
		perror("socket listen");
		return -1;
	}
	DEBUG();

	while(1) {
		DEBUG();
		clilen = sizeof(cliaddr);
		if ( (conn_fd = accept(sock_fd, (SA *)&cliaddr, &clilen)) < 0) {
			if (errno == EINTR) {
				continue;
			} else {
				printf("accept error");
				return 0;
			}
		}
		if ( (pid = fork()) == 0) {
			close(sock_fd);
			read_code(conn_fd, fd_kb);
			exit(0);
		}
		close(conn_fd);
		
	}

	closelog(); 
    close(fd_kb);
    close(sock_fd);
}

/**
 * read key_code from client
 * @param sockfd [ socket descriptor ]
 * @param fd_kb  [ file descriptor ]
 */
static void read_code(int sockfd, int fd_kb) {
	char buf[128];
	int n;
	
	while (1) {
		memset(buf, 0, 128);
		if ( (n = read(sockfd, buf, 128)) < 0) {
			printf("read error\n");
			return ;
		} else if (n == 0) {
			printf("read end\n");
			return;
		}
		buf[n] = 0;
		printf("buf = %s\n", buf);
		if (buf[0] == 'S') {
			int code[2] = {KEY_LEFTSHIFT, KEY_F5};
			simulate_key(fd_kb, code, 2);
		} else {
			int code[1] = {atoi(buf)};
			simulate_key(fd_kb, code, 1);
		}
	}
	
}

struct event_send {
	int fd;
	int type;
	int value;
	int code;
};

/**
 * send key code to system
 * @param fd    [ refer to a /dev/input/eventX ]
 * @param type  [ EV_KEY, EV_SYN ]
 * @param value [ 1 is pressed, 0 is released, 2 is long pressed ]
 * @param code  [ the key code, please see <linux/input.h> ]
 */
static void send_code(int fd, int type, int value, int code) {
	struct input_event event;
	gettimeofday(&event.time, 0);
	// 发送事件
	event.type = type;
	event.value = value;
	event.code = code;
	write(fd, &event, sizeof(event));
	// 同步至系统
	event.type = EV_SYN;
	event.value = 0;
	event.code = SYN_REPORT;
	write(fd, &event, sizeof(event));
}

/**
 * simulate_key
 * @param fd   [ file descriptor ]
 * @param kval [ store key code ]
 * @param n    [ 1: one kye, 2: combination key ]
 */
static void simulate_key(int fd, int *kval, int n) {

	if (n == 1) {
		send_code(fd, EV_KEY, 1, kval[0]);
		send_code(fd, EV_KEY, 0, kval[0]);
	} else if (n == 2) {
		send_code(fd, EV_KEY, 1, kval[0]);
		send_code(fd, EV_KEY, 1, kval[1]);
		send_code(fd, EV_KEY, 0, kval[1]);
		send_code(fd, EV_KEY, 0, kval[0]);
	}
}